package com.yxw.live_vod_boot.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yxw.live_vod_boot.dto.*;
import com.yxw.live_vod_boot.entity.YxLiveShopEntity;
import com.yxw.live_vod_boot.entity.YxOnDemandVideoEntity;
import com.yxw.live_vod_boot.entity.YxUploadVideoReviewEntity;
import com.yxw.live_vod_boot.entity.YxVodProductEntity;
import com.yxw.live_vod_boot.enums.MqttTopicEnum;
import com.yxw.live_vod_boot.mapper.OnDemandVideoMapper;
import com.yxw.live_vod_boot.mapper.OnDemandVideoReviewMapper;
import com.yxw.live_vod_boot.mapper.ShopMapper;
import com.yxw.live_vod_boot.mapper.VodProductMapper;
import com.yxw.live_vod_boot.mqtt.MqttGateway;
import com.yxw.live_vod_boot.service.OnDemandVideoReviewService;
import com.yxw.live_vod_boot.service.SysNoticeService;
import com.yxw.live_vod_boot.utils.HuaWeiObsUtil;
import com.yxw.live_vod_boot.utils.JsonUtils;
import com.yxw.live_vod_boot.utils.PageUtils;
import com.yxw.live_vod_boot.utils.VolcanoEngineUtil;
import com.yxw.live_vod_boot.vo.HsVideoReviewVo;
import com.yxw.live_vod_boot.vo.VodMqttDelayedVo;
import com.yxw.live_vod_boot.vo.VolcanoVideoInfoVO;
import com.yxw.live_vod_facade.dto.PageVideoReviewsDTO;
import com.yxw.live_vod_facade.dto.VideoReviewHandelDTO;
import com.yxw.live_vod_facade.enums.NoticeTypeEnum;
import com.yxw.live_vod_facade.vo.VideoReviewVO;
import com.yxw.yxnet_cd_center.common.constant.CommonConstant;
import com.yxw.yxnet_cd_center.common.dto.PageVO;
import com.yxw.yxnet_cd_center.common.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class OnDemandVideoReviewServiceImpl extends ServiceImpl<OnDemandVideoReviewMapper, YxUploadVideoReviewEntity> implements OnDemandVideoReviewService {
    
    @Autowired
    private OnDemandVideoReviewMapper onDemandVideoReviewMapper;

    @Autowired
    private ShopMapper shopMapper;

    @Autowired
    private VolcanoEngineUtil volcanoEngineUtil;

    @Autowired
    private OnDemandVideoMapper onDemandVideoMapper;

    @Autowired
    private SysNoticeService sysNoticeService;

    @Autowired
    private HuaWeiObsUtil huaWeiObsUtil;

    @Autowired
    private MqttGateway mqttGateway;

    @Autowired
    private VodProductMapper vodProductMapper;

    /**
     * 新增视频审核信息
     * @param reviewDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public VideoReviewVO addVideoReview(VideoReviewDTO reviewDTO) {
        UploadVideoDTO dto = reviewDTO.getDto();
        MultipartFile videoFile = reviewDTO.getVideoFile();
        YxUploadVideoReviewEntity videoReviewEntity = new YxUploadVideoReviewEntity();
        videoReviewEntity.setReviewVideoName(videoFile.getOriginalFilename());
        videoReviewEntity.setTitel(dto.getTitel());
        videoReviewEntity.setReviewVideoSize(new BigDecimal(videoFile.getSize()/1024.0/1024.0));
        videoReviewEntity.setReviewVideoType(CommonConstant.ONE);
        videoReviewEntity.setReviewVideoFormat(videoFile.getOriginalFilename().substring(videoFile.getOriginalFilename().lastIndexOf(CommonConstant.POINT),videoFile.getOriginalFilename().length()));
        videoReviewEntity.setReviewVideoUrl(reviewDTO.getVideoPath());
        videoReviewEntity.setCoverSource(CommonConstant.TWO);
        videoReviewEntity.setCoverUrl(reviewDTO.getCoverPath());
        //查询店铺信息
        LambdaQueryWrapper<YxLiveShopEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(true,YxLiveShopEntity::getLiveShopId,dto.getShopId());
        YxLiveShopEntity shopEntity = shopMapper.selectOne(queryWrapper);
        videoReviewEntity.setUserId(shopEntity.getUserId());
        videoReviewEntity.setUserName(shopEntity.getUserName());
        videoReviewEntity.setShopId(shopEntity.getLiveShopId());
        videoReviewEntity.setShopName(shopEntity.getShopName());
        videoReviewEntity.setExamineStatus(CommonConstant.ONE);
        videoReviewEntity.setCreateTime(new Date());
        videoReviewEntity.setPublishStatus(CommonConstant.ONE);
        videoReviewEntity.setVideoDescribe(reviewDTO.getDto().getTitel());
        videoReviewEntity.setPublicFlag(reviewDTO.getDto().getPublicFlag());
        videoReviewEntity.setVideoKey(reviewDTO.getVideoKey());
        videoReviewEntity.setCoverKey(reviewDTO.getCoverKey());
        baseMapper.insert(videoReviewEntity);
        VideoReviewVO vo = new VideoReviewVO();
        BeanUtils.copyProperties(videoReviewEntity, vo);
        return vo;
    }

    /**
     * 视频审核处理
     * @param dto
     * 审核成功与否都发一条审核记录消息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handle(VideoReviewHandelDTO dto) {
        //是否正常执行，默认是，失败时需要删除火山已上传视频
        Boolean success=true;
        //火山引擎ID
        String vid = "";
        YxUploadVideoReviewEntity reviewEntity=null;
        try {
            //查询未审核或者审核失败的审核信息
            LambdaQueryWrapper<YxUploadVideoReviewEntity> queryWrappe=new LambdaQueryWrapper();
            queryWrappe.eq(true,YxUploadVideoReviewEntity::getReviewVideoId,dto.getBussId());
            queryWrappe.ne(true,YxUploadVideoReviewEntity::getExamineStatus,CommonConstant.TWO);
            queryWrappe.ne(true,YxUploadVideoReviewEntity::getExamineStatus,4);
            reviewEntity = baseMapper.selectOne(queryWrappe);
            if(null==reviewEntity){
                throw new BaseException("未查询到需要审核的视频");
            }
            Integer status = dto.getStatus();
            //审核成功
            if (CommonConstant.ZERO.compareTo(status) == 0) {
                HsVideoReviewVo hsVideo = new HsVideoReviewVo();
                String reviewVideoUrl = reviewEntity.getReviewVideoUrl();
                //上传视频到火山引擎
                UploadVideoToHsDTO videoToHsDTO = new UploadVideoToHsDTO();
                videoToHsDTO.setExamineId(reviewEntity.getReviewVideoId());
                videoToHsDTO.setFileName(reviewEntity.getReviewVideoName());
                videoToHsDTO.setLocalfileUrl(reviewVideoUrl);
                //url上传返回，返回火山上传路径对应的ID
                String jobId= volcanoEngineUtil.uploadMediaByUrl(videoToHsDTO);
                //保存该ID到审核表，防止二次上传
                LambdaUpdateWrapper<YxUploadVideoReviewEntity> updateWrappe=new LambdaUpdateWrapper();
                updateWrappe.set(true,YxUploadVideoReviewEntity::getJobId,jobId).eq(true,YxUploadVideoReviewEntity::getReviewVideoId,reviewEntity.getReviewVideoId());
                baseMapper.update(null,updateWrappe);
                //通过ID查询上传状态,完成状态才会返回火山视频ID,上传有个时间间隔，这里采用2次3秒的延迟查询
//                for (int i = 0; i < 2; i++) {
//                    vid = volcanoEngineUtil.queryUploadTaskInfo(jobId,reviewEntity.getReviewVideoId());
//                    //查询到以后返回
//                    if (StringUtils.isNotBlank(vid)) {
//                        break;
//                    }
//                    Thread.sleep(3000);
//                }
                //这里在火山引擎有回调确认函数，需要域名，不利于测试，就选择用这个延迟消息自己去拉取，未获取到播放地址视频状态未审核通过未发布未发布状态，用户不会看到这个视频列表。
                vid = volcanoEngineUtil.queryUploadTaskInfo(jobId,reviewEntity.getReviewVideoId());
                //查询到id以后自动发布视频，发布的视频才能生成播放地址
                if (StringUtils.isNotBlank(vid)) {
                    //发布
                    volcanoEngineUtil.publishStatus(vid,reviewEntity.getReviewVideoId());
                    //查询播放地址
                    VolcanoVideoInfoVO playInfo = volcanoEngineUtil.getPlayInfo(vid, reviewEntity.getReviewVideoId());
                    hsVideo.setPlayUrl(playInfo.getPlayUrl());
                    hsVideo.setDuration(playInfo.getDuration());
                }else{
                    //发送一个30s的延时消息队列去再次获取播放地址
                    VodMqttDelayedVo delayedVO = new VodMqttDelayedVo();
                    delayedVO.setJobId(jobId);
                    delayedVO.setReviewVideoId(reviewEntity.getReviewVideoId());
                    mqttGateway.sendToMqtt(MqttTopicEnum.VOD_PLAYURL_DELAYED_PRODUCT.getTopic(), CommonConstant.TWO, true, JsonUtils.toJson(delayedVO));
                }
                hsVideo.setVid(vid);
                hsVideo.setJobId(jobId);
                reviewEntity.setExamineStatus(2);
                reviewEntity.setPublishStatus(1);
                reviewEntity.setExamineTime(new Date());
                reviewEntity.setExamineUserId(dto.getUserId());
                reviewEntity.setExamineUserName(dto.getUserName());
                reviewEntity.setExamineDescrible(dto.getExamineDescrible());
                //更新审核单据状态
                baseMapper.updateById(reviewEntity);
                //写视频信息
                YxOnDemandVideoEntity videoEntity = buildeVideoEntity(hsVideo, reviewEntity);
                onDemandVideoMapper.insert(videoEntity);
                //商品挂到挂到视频下
                LambdaUpdateWrapper<YxVodProductEntity> updateProWapper=new LambdaUpdateWrapper();
                updateProWapper.set(YxVodProductEntity::getVideoId,videoEntity.getVideoId());
                updateProWapper.eq(YxVodProductEntity::getReviewVideoId,reviewEntity.getReviewVideoId());
                vodProductMapper.update(null,updateProWapper);
                //扣减店铺存储空间大小
                LambdaQueryWrapper<YxLiveShopEntity> shopWrappe=new LambdaQueryWrapper();
                shopWrappe.eq(true,YxLiveShopEntity::getLiveShopId,videoEntity.getShopId());
                YxLiveShopEntity shop = shopMapper.selectOne(shopWrappe);
                if(null==shop){
                    throw new BaseException("店铺不存在！");
                }
                shop.setRemainStorage(shop.getStorage().subtract(videoEntity.getVideoSize()));
                shopMapper.updateById(shop);
            } else {//失败
                if(StringUtils.isBlank(dto.getExamineDescrible())){
                    throw new BaseException("审核拒绝时,拒绝原因必填");
                }
                reviewEntity.setExamineStatus(3);
                reviewEntity.setPublishStatus(0);
                reviewEntity.setExamineTime(new Date());
                reviewEntity.setExamineUserId(dto.getUserId());
                reviewEntity.setExamineUserName(dto.getUserName());
                reviewEntity.setExamineDescrible(dto.getExamineDescrible());
                baseMapper.updateById(reviewEntity);
            }
            try {
                SendInteractMsgDto msgDto=new SendInteractMsgDto();
                if(0==status){
                    msgDto.setType(NoticeTypeEnum.VOD_PASS_THROUGH);
                }else{
                    msgDto.setType(NoticeTypeEnum.VOD_REFUSE);
                }
                msgDto.setShopName(reviewEntity.getShopName());
                msgDto.setShopId(reviewEntity.getShopId());
                msgDto.setUserId(reviewEntity.getUserId());
                msgDto.setBussId(String.valueOf(reviewEntity.getReviewVideoId()));
                //发送审核系统消息
                sysNoticeService.sendNotice(msgDto);
            }catch (Exception e){
                log.error("审核消息发送失败：==================================================>"+e.getMessage());
            }
        }catch (Exception e){
            success=false;
            log.error("审核异常信息==================================================>"+e.getMessage());
            throw new BaseException("审核异常信息:"+e.getMessage());
        }finally {
            //删除火山已上传视频
            if(!success){
                try {
                    if(StringUtils.isNotBlank(vid)){
                        List<String> vidList=new ArrayList<>();
                        vidList.add(vid);
                        volcanoEngineUtil.deleteMedia(vidList,reviewEntity.getReviewVideoId());
                    }
                }catch (Exception e){
                    log.error("删除火山引擎文件失败：==================================================>"+e.getMessage());
                }
            }
        }
    }

    /**
     * 查询待审核视频列表
     * @param dto
     * @return
     */
    @Override
    public PageVO<VideoReviewVO> pageVideoReviews(PageVideoReviewsDTO dto) {
        List<VideoReviewVO> volist=new ArrayList<>();
        Page<YxUploadVideoReviewEntity> page = new Page<>(dto.getCurrPage(), dto.getPageSize());
        LambdaQueryWrapper<YxUploadVideoReviewEntity> queryWrapper =new  LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(dto.getShopId()),YxUploadVideoReviewEntity::getShopId,dto.getShopId());
        List<Integer> statusList=new ArrayList<>();
        statusList.add(1);
        statusList.add(3);
        queryWrapper.in(true,YxUploadVideoReviewEntity::getExamineStatus,statusList);
        queryWrapper.orderByDesc(YxUploadVideoReviewEntity::getCreateTime);
        Page<YxUploadVideoReviewEntity> reviewEntityPage = baseMapper.selectPage(page, queryWrapper);
        if(null!=reviewEntityPage.getRecords() && !reviewEntityPage.getRecords().isEmpty()){
            volist = BeanUtil.copyToList(reviewEntityPage.getRecords(), VideoReviewVO.class);
        }
        return PageUtils.get(page,volist);
    }

    /**
     * 审核视频删除
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteVideoReviewByIds(VideoReviewDeleteDTO dto) {
        List<Long> videoReviewIdList = dto.getVideoReviewIdList();
        for (Long videoReviewId: videoReviewIdList) {
            YxUploadVideoReviewEntity reviewEntity = baseMapper.selectById(videoReviewId);
            huaWeiObsUtil.deleteFile(reviewEntity.getCoverKey());
            huaWeiObsUtil.deleteFile(reviewEntity.getVideoKey());
        }
        baseMapper.deleteBatchIds(videoReviewIdList);
    }

    /**
     * 根据id查询审核详情
     * @param reviewVideoId
     * @return
     */
    @Override
    public VideoReviewVO getVideoReviewById(Long reviewVideoId) {
        VideoReviewVO vo =new VideoReviewVO();
        YxUploadVideoReviewEntity reviewEntity = baseMapper.selectById(reviewVideoId);
        if(null!=reviewEntity){
            BeanUtils.copyProperties(reviewEntity, vo);
        }
        return vo;
    }

    /**
     * 获取点播视频播放地址任务
     * @param vo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void getVodPlayUrlByJobIdTask(VodMqttDelayedVo vo) {
        try {
            if (null == vo || StringUtils.isBlank(vo.getJobId()) || null==vo.getReviewVideoId()) {
                log.error("获取点播视频播放地址任务参数为空");
            }else {
                Long reviewVideoId = vo.getReviewVideoId();
                String jobId = vo.getJobId();
                String vid="";
                //循环5次获取,每次间隔5s
                for (int i = 0; i < 5; i++) {
                    vid = volcanoEngineUtil.queryUploadTaskInfo(jobId,reviewVideoId);
                    //查询到以后返回
                    if (StringUtils.isNotBlank(vid)) {
                        break;
                    }
                    Thread.sleep(5000);
                }
                //查询到id以后自动发布视频，发布的视频才能生成播放地址
                if (StringUtils.isNotBlank(vid)) {
                    //发布
                    volcanoEngineUtil.publishStatus(vid,reviewVideoId);
                    //查询播放地址
                    VolcanoVideoInfoVO playInfo = volcanoEngineUtil.getPlayInfo(vid,reviewVideoId);
                    //查询对应视频
                    LambdaQueryWrapper<YxOnDemandVideoEntity> queryWapper=new LambdaQueryWrapper();
                    queryWapper.eq(YxOnDemandVideoEntity::getReviewVideoId,reviewVideoId);
                    YxOnDemandVideoEntity videoEntity = onDemandVideoMapper.selectOne(queryWapper);
                    if(null!=videoEntity){
                        videoEntity.setPlayUrl(playInfo.getPlayUrl());
                        videoEntity.setDuration(playInfo.getDuration());
                        videoEntity.setVId(vid);
                        onDemandVideoMapper.updateById(videoEntity);
                    }
                }
            }
        }catch (Exception e){
            log.error("获取点播视频播放地址任务异常{}",e.getMessage());
        }
    }

    //-----------------------------------------------------------------------------------------------------
    /**
     * 组装视频信息
     */
    private YxOnDemandVideoEntity buildeVideoEntity(HsVideoReviewVo hsVideo, YxUploadVideoReviewEntity reviewEntity) {
        YxOnDemandVideoEntity entity = new YxOnDemandVideoEntity();
        entity.setVideoName(reviewEntity.getReviewVideoName());
        if(StringUtils.isBlank(hsVideo.getVid())){
            //未生成播放地址时，状态为未发布
            entity.setPublishStatus(CommonConstant.ONE);
        }else{
            entity.setPublishStatus(CommonConstant.TWO);
        }
        entity.setVId(hsVideo.getVid());
        entity.setSpaceName("");
        entity.setReviewVideoId(reviewEntity.getReviewVideoId());
        entity.setClassId(null);
        entity.setVideoSize(reviewEntity.getReviewVideoSize());
        entity.setCoverUrl(reviewEntity.getCoverUrl());
        entity.setPublicFlag(reviewEntity.getPublicFlag());
        entity.setPayType(CommonConstant.ZERO);
        entity.setCreateTime(new Date());
        entity.setUpdateTime(new Date());
        entity.setTopFlag(CommonConstant.ZERO);
        entity.setVideoDescribe(reviewEntity.getVideoDescribe());
        entity.setStorageType(CommonConstant.ONE);
        entity.setPlayUrl(hsVideo.getPlayUrl());
        entity.setPlayToken("");
        entity.setShopId(reviewEntity.getShopId());
        entity.setShopName(reviewEntity.getShopName());
        entity.setVideoStatus(CommonConstant.ONE);
        entity.setTitel(reviewEntity.getTitel());
        entity.setJobId(hsVideo.getJobId());
        entity.setDuration(hsVideo.getDuration());
        entity.setUserId(reviewEntity.getUserId());
        entity.setUserName(reviewEntity.getUserName());
        return entity;
    }
}
